#include "SystemRoot_Test.h"

#include <Poco/Exception.h>
#include "server/misc/SystemRoot.h"
#include "server/net/NetworkControl.h"
#include "misc/Event.h"
#include "server/misc/Config.h"
#include <string.h>
#include <iostream>
#include <iomanip>
#include <sstream>
/*********************************************************/
std::string SystemRootTest::name()
{
	return("SystemRoot");
}
/*********************************************************/
bool SystemRootTest::runUnitTests()
{
	bool result = true;

	if ( !cleanStartStopTest() ) result = false;
	if ( !doubleStartStopTest() ) result = false;
	if ( !doubleStopTest() ) result = false;
	if ( !idleStopTest() ) result = false;
	if ( !quitFlagStopTest() ) result = false;
	if ( !onStartRingCreationTest() ) result = false;

	return( result ) ;
}
/*********************************************************/
bool SystemRootTest::onStartRingCreationTest()
{
	try {
		NetworkControl& net = NetworkControl::Instance();
		SystemRoot	sysRoot;
		sysRoot.start();

		// Wait for the networkcontroller to create a ring
		sleep((MULTICAST_RING_CREATE_PAUSE/1000000) + 1);

		// Check if we get the correct ring information
		std::string	ringinfo = net.getRingInformation();
		
		std::ostringstream ostr;
		ostr << "Ring in multicastgroup: " << "239.0.0.1" << ":" << 5001 << std::endl;
		ostr << "--------------------------------------" << std::endl;
		ostr << std::setw(25) << std::left  << "Addr" << std::setw(25) << "Pred" << std::setw(25) << "Succ" << std::setw(40) << "Hash" << std::endl;
		ostr << std::setw(25) << net.getLocalAddress() << std::setw(25) << net.getLocalAddress() << std::setw(25) << net.getLocalAddress() << std::setw(40) << "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" << std::endl;

		sysRoot.stop();

		std::cout << "Running: onStartRingCreationTest()";
		std::cout.flush();

		// Check if the ring message was correclty stored in the network control class
		if ( strcmp(ostr.str().c_str(), ringinfo.c_str()) == 0 ) {
			std::cout << "... success!" << std::endl;
			return true;
		} else {
			std::cout << "... failed! Invalid ring information stored in NetworkControl" << std::endl;
			std::cout << "NetworkControl returned: " << std::endl;
			std::cout << ringinfo << std::endl;
			std::cout << "Expected: " << std::endl;
			std::cout << ostr.str() << std::endl;
			return false;
		}
	} catch(...) {
		std::cout << "... failed! Caught unknown exception, expected none" << std::endl;
		return false;
	}

	std::cout << "... success!" << std::endl;
	return true;
}
/*********************************************************/
bool SystemRootTest::quitFlagStopTest()
{
	try {
		Config& cfg = Config::Instance();
		Event* event = Event::Instance(cfg.getQuitEvent());
		SystemRoot	sysRoot;

		sysRoot.start();
		event->set();
		sysRoot.run();
		sysRoot.stop();

		std::cout << "Running: quitFlagStopTest()" ;
		std::cout << "... success!" << std::endl;
		return( true );
	} catch(...) {
		std::cout << "Running: quitFlagStopTest()" ;
		std::cout << "... failed! with unknown exception!" << std::endl;
		return( false );
	}
}
/*********************************************************/
bool SystemRootTest::doubleStopTest()
{
	try {
		SystemRoot	sysRoot;
		sysRoot.start();
		sysRoot.stop();
	} catch(...) {
		std::cout << "Running: doubleStopTest()";
		std::cout.flush();
		std::cout << "... failed with unknown exception" << std::endl;
		return( false );
	}
	std::cout << "Running: doubleStopTest()";
	std::cout.flush();
	std::cout << "... success!" << std::endl;
	return( true );
}
/*********************************************************/
bool SystemRootTest::idleStopTest()
{
	try {
		SystemRoot	sysRoot;
		sysRoot.stop();
	} catch(...) {
		std::cout << "Running: idleStopTest()";
		std::cout.flush();
		std::cout << "... failed with unknown exception" << std::endl;
		return( false );
	}
	std::cout << "Running: idleStopTest()";
	std::cout.flush();
	std::cout << "... success!" << std::endl;
	return( true );
}
/*********************************************************/
bool SystemRootTest::cleanStartStopTest()
{
	try {
		SystemRoot	sysRoot;
		sysRoot.start();
		sysRoot.stop();
	} catch(...) {
		std::cout << "Running: cleanStartStopTest()";
		std::cout.flush();
		std::cout << "... failed with unknown exception" << std::endl;
		return( false );
	}
	std::cout << "Running: cleanStartStopTest()";
	std::cout.flush();
	std::cout << "... success!" << std::endl;
	return( true );
}
/*********************************************************/
bool SystemRootTest::doubleStartStopTest()
{
	try {
		SystemRoot	sysRoot;
		sysRoot.start();
		sysRoot.stop();
		sysRoot.start();
		sysRoot.stop();
	} catch(...) {
		std::cout << "Running: doubleStartStopTest()";
		std::cout.flush();
		std::cout << "... failed with unknown exception" << std::endl;
		return( false );
	}
	std::cout << "Running: doubleStartStopTest()";
	std::cout.flush();
	std::cout << "... success!" << std::endl;
	return( true );
}
